/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Source file for the connection base.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#include "owndebug.h"
#include "connection.h"
#include <signal.h>
#include <netdb.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>

//**************************************************************************************
//**************************************************************************************
//**************************************************************************************
int connectionClientConnect(TConnection *con);
int connectionServerConnect(TConnection *con);
//**************************************************************************************
//**************************************************************************************
//**************************************************************************************

TConnection *connectionConstruct(const TConnectionPtr *cp)
{
  // Reserve memory for a new TConnection
  TConnection *con = (TConnection *)malloc(sizeof(TConnection));
  assert(con != NULL);
  
  // Zero the struct the initialize all pointer to NULL per default.
  memset(con, 0, sizeof(TConnection));
  
  // Initialize the provided ConnectionPtr
  connectionInit(con, cp);

  dPrint(8,"Initialized TConnection %p", con);


  return con;
}
//**************************************************************************************

void connectionDestroy(TConnection *con)
{
  dPrint(8,"Destroyed TConnection %p", con);
  // Call deinit. Cleans up the contents, including the dataPtr.
  connectionDeinit(con);

  // Now, free the whole connection element.
  free(con);
}
//**************************************************************************************

int connectionInit(TConnection *con, 
		   const TConnectionPtr *cp)
{
  // Assign link parameters
  con->link = cp;
      
  assert(con->link != NULL);

  return CONNECTION_OK;
}
//**************************************************************************************

const void *connectionGetDataPtr(const TConnection *con)
{
  return con->link->dataPtr;
}
//**************************************************************************************

int connectionDeinit(TConnection *con)
{
  if (con->link) {
    // Call deinit for module
    con->link->deinitFunc(con->link->dataPtr);
    
    // Module deinit has been called. As we don't have a DESTROY pointer,
    // we can now safely destroy the 'dataPtr'.
    free(con->link->dataPtr);
    
    // And cleanup pointers.
    con->link = NULL;

    return CONNECTION_OK;

  } else {
    return -1;

  }
}
//**************************************************************************************

int connectionConnect(TConnection *con)
{
  int result;

  assert(con->link != NULL);
  assert(con->link->connectFunc != NULL);

  result = con->link->connectFunc(con->link->dataPtr);
 
  return result;
}
//**************************************************************************************

int connectionDisconnect(TConnection *con)
{
  int result;

  assert(con->link != NULL);
  assert(con->link->disconnectFunc != NULL);

  result = con->link->disconnectFunc(con->link->dataPtr);
 
  return result;
}
//**************************************************************************************

int connectionSendData(TConnection *con, const unsigned char *buffer, int bufLen)
{

  int result;

  assert(con->link != NULL);
  assert(con->link->sendFunc != NULL);

  result = con->link->sendFunc(con->link->dataPtr, buffer, bufLen);

  return result;
}
//**************************************************************************************

int connectionReceiveData(TConnection *con, unsigned char *buffer, int bufLen)
{
  int result;

  assert(con->link != NULL);
  assert(con->link->receiveFunc != NULL);

  result = con->link->receiveFunc(con->link->dataPtr, buffer, bufLen);

  return result;
}
//**************************************************************************************

int connectionReceiveDataTimed(TConnection *con, unsigned char *buffer, int bufLen, int timeout_ms)
{
  int result;

  assert(con->link != NULL);
  assert(con->link->receiveTimedFunc != NULL);

  result = con->link->receiveTimedFunc(con->link->dataPtr, buffer, bufLen, timeout_ms);

  return result;
}
//**************************************************************************************

int connectionGetHandle(const TConnection *con)
{
  int result;

  assert(con->link != NULL);
  assert(con->link->getHandleFunc != NULL);

  result = con->link->getHandleFunc(con->link->dataPtr);

  return result;
}
//**************************************************************************************

const char *connectionGetPeerIP(const TConnection *con)
{
  const char * result = NULL;
  assert(con->link != NULL);

  // Test whether we have a pointer to this function
  if (con->link->getPeerIPFunc != NULL) 
    result = con->link->getPeerIPFunc(con->link->dataPtr);

  return result; 
}
//**************************************************************************************

int connectionGetPeerPort(const TConnection *con)
{
  int result = -1;
  assert(con->link != NULL);

  // Test whether we have a pointer to this function
  if (con->link->getPeerPortFunc != NULL) 
    result = con->link->getPeerPortFunc(con->link->dataPtr);

  return result; 
}
//**************************************************************************************
//**************************************************************************************
//**************************************************************************************
//**************************************************************************************

